package com.xhwl.logistics.service.business;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xhwl.common.enums.device.DeviceOnlineStatusEnum;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.logistics.bo.cent.DeviceBO;
import com.xhwl.logistics.entity.VehicleBlacklist;
import com.xhwl.logistics.entity.VehiclePassage;
import com.xhwl.logistics.enums.VehiclePassTypeEnum;
import com.xhwl.logistics.service.cent.QueryDeviceSecondService;
import com.xhwl.logistics.service.impl.VehicleBlacklistServiceImpl;
import com.xhwl.logistics.service.impl.VehiclePassageServiceImpl;
import com.xhwl.logistics.service.impl.kafka.VehicleAlarmKafkaServiceImpl;
import com.xhwl.logistics.service.impl.redis.VehicleExceptionRedisServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.util.Optionals;
import org.springframework.scheduling.annotation.Async;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

//@Service
@Slf4j
public class VehicleAlarmBusinessService {

    @Autowired
    private VehicleAlarmKafkaServiceImpl vehicleAlarmKafkaService;

    @Autowired
    private VehicleExceptionRedisServiceImpl vehicleExceptionRedisService;

    @Autowired
    private QueryDeviceSecondService queryDeviceSecondService;

    @Autowired
    private VehicleBlacklistServiceImpl vehicleBlacklistService;

    @Autowired
    private VehiclePassageServiceImpl vehiclePassageService;


    /**
     * 进记录异常时，推送告警
     * @param projectId
     * @param passType
     * @param imgUrl
     */
    @Async("threadPoolTaskExecutorForAlarm")
    public void sendAlarmForCarInExceptionPass(Integer projectId, Integer passType, String imgUrl){
        VehiclePassTypeEnum vehiclePassTypeEnum = VehiclePassTypeEnum.toVehiclePassTypeEnum(passType);
        if (VehiclePassTypeEnum.EXCEPTION == vehiclePassTypeEnum) {
            List<DeviceBO> deviceBOList = queryDeviceSecondService.queryDevicesByProjectId(projectId);

            Optional<Integer> optionalDeviceId = deviceBOList.stream().map(DeviceBO::getId).min(Comparator.naturalOrder());
            Optionals.ifPresentOrElse(
                    optionalDeviceId,
                    id -> {
                        vehicleAlarmKafkaService.sendAlarmForVehicleCarInExceptionPass(projectId, id, imgUrl);
                    },
                    () -> {
                        vehicleExceptionRedisService.exceptionMessage("car-in-exception-pass", "该项目找不到最小的设备id，没法进行车辆进场异常放行的告警推送");
                    });
        }
    }

    /**
     * 出记录异常时，推送告警
     * @param projectId
     * @param passType
     * @param imgUrl
     */
    @Async("threadPoolTaskExecutorForAlarm")
    public void sendAlarmForCarOutExceptionPass(Integer projectId, Integer passType, String imgUrl){
        VehiclePassTypeEnum vehiclePassTypeEnum = VehiclePassTypeEnum.toVehiclePassTypeEnum(passType);
        if (VehiclePassTypeEnum.EXCEPTION == vehiclePassTypeEnum) {
            List<DeviceBO> deviceBOList = queryDeviceSecondService.queryDevicesByProjectId(projectId);

            Optional<Integer> optionalDeviceId = deviceBOList.stream().map(DeviceBO::getId).min(Comparator.naturalOrder());
            Optionals.ifPresentOrElse(
                    optionalDeviceId,
                    id -> {
                        vehicleAlarmKafkaService.sendAlarmForVehicleCarOutExceptionPass(projectId, id, imgUrl);
                    },
                    () -> {
                        vehicleExceptionRedisService.exceptionMessage("car-out-exception-pass", "该项目找不到最小的设备id，没法进行车辆出场异常放行的告警推送");
                    });
        }
    }

    @Async("threadPoolTaskExecutorForAlarm")
    public void sendAlarmForKeTopCarInExceptionPass(Integer projectId, Integer passType, String imgUrl,String thirdId) {
        VehiclePassTypeEnum vehiclePassTypeEnum = VehiclePassTypeEnum.toVehiclePassTypeEnumByKeTop(passType);
        if (VehiclePassTypeEnum.EXCEPTION == vehiclePassTypeEnum) {
            List<DeviceBO> deviceBOList = queryDeviceSecondService.queryDevicesByProjectId(projectId);

            Map<String, DeviceBO> mapForDevice = deviceBOList.stream().collect(Collectors.toMap(s -> s.getNumber(), Function.identity()));

            //获取通道信息，将设备与通道进行关联
            List<VehiclePassage> vehiclePassageList = vehiclePassageService.list(new LambdaQueryWrapper<VehiclePassage>().eq(VehiclePassage::getProjectId, projectId));
            Map<String, VehiclePassage> mapForPassage = vehiclePassageList.stream().collect(Collectors.toMap(
                    s -> StringUtils.substringAfterLast(s.getThirdPassageId(), "-"), Function.identity()));

            Integer id = mapForDevice.get(mapForPassage.get(thirdId).getRemark()).getId();

            if(id!=null){
                vehicleAlarmKafkaService.sendAlarmForVehicleCarInExceptionPass(projectId, id, imgUrl);
            }else{
                vehicleExceptionRedisService.exceptionMessage("car-in-exception-pass", "该项目找不到设备id，没法进行车辆进场异常放行的告警推送");
            }
        }
    }

    @Async("threadPoolTaskExecutorForAlarm")
    public void sendAlarmForKeTopCarOutExceptionPass(Integer projectId, Integer passType, String imgUrl,String thirdId) {
        VehiclePassTypeEnum vehiclePassTypeEnum = VehiclePassTypeEnum.toVehiclePassTypeEnumByKeTop(passType);
        if (VehiclePassTypeEnum.EXCEPTION == vehiclePassTypeEnum) {
            List<DeviceBO> deviceBOList = queryDeviceSecondService.queryDevicesByProjectId(projectId);


            Map<String, DeviceBO> mapForDevice = deviceBOList.stream().collect(Collectors.toMap(s -> s.getNumber(), Function.identity()));

            //获取通道信息，将设备与通道进行关联
            List<VehiclePassage> vehiclePassageList = vehiclePassageService.list(new LambdaQueryWrapper<VehiclePassage>().eq(VehiclePassage::getProjectId, projectId));
            Map<String, VehiclePassage> mapForPassage = vehiclePassageList.stream().collect(Collectors.toMap(
                    s -> StringUtils.substringAfterLast(s.getThirdPassageId(), "-"), Function.identity()));

            Integer id = mapForDevice.get(mapForPassage.get(thirdId).getRemark()).getId();


            if(id!=null){
                vehicleAlarmKafkaService.sendAlarmForVehicleCarOutExceptionPass(projectId, id, imgUrl);
            }else{
                vehicleExceptionRedisService.exceptionMessage("car-in-exception-pass", "该项目找不到设备id，没法进行车辆进场异常放行的告警推送");
            }
        }
    }

    @Async("threadPoolTaskExecutorForAlarm")
    public void sendAlarmForKeTopBlacklist(Integer projectId, String plateNumber, String imgUrl) {
        Optional<VehicleBlacklist> optionalVehicleBlacklist = vehicleBlacklistService.queryVehicleBlacklist(projectId, plateNumber);
        optionalVehicleBlacklist.ifPresent(vehicleBlacklist -> {
            List<DeviceBO> deviceBOList = queryDeviceSecondService.queryDevicesByProjectId(projectId);

            Optional<Integer> optionalDeviceId = deviceBOList.stream().map(DeviceBO::getId).min(Comparator.naturalOrder());
            Optionals.ifPresentOrElse(
                    optionalDeviceId,
                    id -> {
                        String content = "车场：" + vehicleBlacklist.getParkingLotName() + "出现黑名单车辆，车牌号码为" + plateNumber;
                        vehicleAlarmKafkaService.sendAlarmForVehicleBlacklist(projectId, id, imgUrl, content);
                    },
                    () -> {
                        vehicleExceptionRedisService.exceptionMessage("plate-number-blacklist", "该项目找不到最小的设备id，没法进行车辆黑名单的告警推送");
                    });
        });
    }
    public void sendAlarmForCoSonDeviceStatus(Integer projectId,Integer Status){
        try {
            if (Status != DeviceOnlineStatusEnum.ONLINE.getId()) {
                List<DeviceBO> deviceBOList = queryDeviceSecondService.queryDevicesByProjectId(projectId);
                Optional<Integer> optionalDeviceId = deviceBOList.stream().map(DeviceBO::getId).min(Comparator.naturalOrder());
                Optionals.ifPresentOrElse(
                        optionalDeviceId,
                        id -> {
                            vehicleAlarmKafkaService.sendAlarmForVehicleDeviceStatusOffline(projectId, id);
                        },
                        () -> {
                            vehicleExceptionRedisService.exceptionMessage("device-alarm-exception", "该项目找不到最小的设备id，没法进行车辆出场异常放行的告警推送");
                        });
            }
        }catch (Exception e){
            log.error("设备告警请求发生异常错误!错误原因：" + e.getMessage());
            throw new BusinessException("设备告警请求发生异常错误!错误原因：" + e.getMessage());
        }
    }

}
